/**
 ***********************************************************************************************************
 * 
 ***********************************************************************************************************
 * @file RBHardwareBufferManager.h
 ***********************************************************************************************************/

#ifndef __RBHARDWAREBUFFERMANAGER_H__
#define __RBHARDWAREBUFFERMANAGER_H__

#ifdef  HEADER_ONCE
#pragma HEADER_ONCE
#endif

#ifdef  HEADER_MSG
#pragma HEADER_MSG(RBHardwareBufferManager.h)
#endif

/***********************************************************************************************************
 * Includes
 ***********************************************************************************************************/
#include "RBMain/rb_hw_buffer_usage.h"
#include "RBMain/RBCommon.h"
#include "RBMemObject.h"
#include "RBPixelFormat.h"
#include "RBIndexBufferType.h"
#include "RBTextureType.h"

/***********************************************************************************************************
 * Forward declarations
 ***********************************************************************************************************/
class RBPixelBuffer;
class RBTexture;
class RBVertexBuffer;
class RBVertexElement;
class RBVertexDeclaration;
class RBIndexBuffer;
class RBStream;
class RBEffect;
class RBShaderResourceView;
class RBShaderSamplerState;
class RBRasterizerState;
class RBBlendState;
class RBDepthStencilState;
struct RBRenderTargetView;
struct RBDepthStencilView;
class RBHardwareBuffer;
class RBMaterial;
class RBEffectPass;

/***********************************************************************************************************
 * Classes
 ***********************************************************************************************************/

class RBHardwareBufferManager : public RBMemObject
{
public:
				                    RBHardwareBufferManager     ();
    virtual                        ~RBHardwareBufferManager     ();

    virtual RBVertexBuffer*         CreateVertexBuffer          (uint32 uiUsage, uint32 uiVertexSize, uint32 uiVertexCount, const void* pInitData) = 0;

    virtual RBIndexBuffer*          CreateIndexBuffer           (uint32 uiUsage, RBIndexBufferType::EType eIndexType, 
                                                                 uint32 uiIndexCount, const void* pInitData) = 0;
    
    virtual RBVertexDeclaration*    CreateVertexDeclaration     (RBVertexElement* pElements, uint32 uiNumElements, RBEffectPass* pEffectPass) = 0;

    virtual RBTexture*              CreateTexture               (const char* pcFilename, uint32 uiUsage = rb_hw_buffer_usage::HBU_DEFAULT) = 0;
    
    virtual RBTexture*              CreateTexture               (uint32 uiUsage, uint32 uiWidth, uint32 uiHeight, 
                                                                 RBPixelFormat eFormat, RBTextureType::EType eType,
                                                                 uint32 uiMips = 0, uint32 uiDepth = 0, uint32 eMemPool = 1) = 0;
    
    virtual RBTexture*              CreateRenderTarget          (uint32 uiUsage, uint32 uiWidth, uint32 uiHeight, RBPixelFormat eFormat, 
                                                                 uint32 uiMSAA) = 0;

    // Helper that creates a resource, a render target view and a shader resource view
    void                            CreateRenderTarget          (uint32 uiWidth, uint32 uiHeight, RBPixelFormat eRenderFormat, uint32 uiMSAA, RBTexture** pTexture, 
                                                                 RBRenderTargetView** pRTT = NULL, RBShaderResourceView** pShaderView = NULL, RBPixelFormat eTextureFormat = PF_UNKNOWN);

    virtual RBShaderResourceView*   CreateShaderResourceView    (RBTexture* pBuffer, RBPixelFormat eFormat = PF_UNKNOWN) = 0;
    virtual RBRenderTargetView*     CreateRenderTargetView      (RBTexture* pBuffer, RBPixelFormat eFormat = PF_UNKNOWN) = 0;
    virtual RBDepthStencilView*     CreateDepthStencilView      (RBTexture* pBuffer, RBPixelFormat eFormat = PF_UNKNOWN) = 0;
    virtual RBShaderSamplerState*   CreateSamplerState          (const class RBTextureSampler& sampler) = 0;
    virtual RBRasterizerState*      CreateRasterizerState       (const RBMaterial& material) = 0;
    virtual RBBlendState*           CreateBlendState            (const RBMaterial& material, uint32 colorWrites) = 0;
    virtual RBDepthStencilState*    CreateDepthStencilState     (const RBMaterial& material) = 0;

    virtual void                    ReleaseNative               (RBHardwareBuffer* pVB) = 0;

    // Serialization

    virtual void                    Write                       (RBVertexDeclaration* pVertexDecl, RBStream& kStream);
    virtual void                    Write                       (RBVertexBuffer* pVertexBuffer, RBStream& kStream);
    virtual void                    Write                       (RBIndexBuffer* pIndexBuffer, RBStream& kStream);
    virtual void                    Write                       (RBTexture* pTexture, RBStream& kStream);

    virtual RBVertexDeclaration*    ReadVertexDeclaration       (RBStream& kStream);
    virtual RBVertexBuffer*         ReadVertexBuffer            (RBStream& kStream);
    virtual RBIndexBuffer*          ReadIndexBuffer             (RBStream& kStream);
    virtual RBTexture*              ReadTexture                 (RBStream& kStream);

     template<class T>
     T*                             Read                        (RBStream& kStream) {}

    template<>
    RBVertexDeclaration*            Read<RBVertexDeclaration>   (RBStream& kStream);

    template<>
    RBVertexBuffer*                 Read<RBVertexBuffer>        (RBStream& kStream);

    template<>
    RBIndexBuffer*                  Read<RBIndexBuffer>         (RBStream& kStream);

    template<>
    RBTexture*                      Read<RBTexture>             (RBStream& kStream);

private:
    friend class RBHardwareBuffer;
    void                            AddBuffer                   (RBHardwareBuffer* pBuffer);
    void                            RemoveBuffer                (RBHardwareBuffer* pBuffer);

protected:
    std::list<RBHardwareBuffer*>    m_aAllocatedBuffers;

};


/***********************************************************************************************************/

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
template<>
inline RBVertexDeclaration* RBHardwareBufferManager::Read<RBVertexDeclaration>( RBStream& kStream )
{
    return ReadVertexDeclaration(kStream);
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
template<>
inline RBVertexBuffer* RBHardwareBufferManager::Read<RBVertexBuffer>( RBStream& kStream )
{
    return ReadVertexBuffer(kStream);
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
template<>
inline RBIndexBuffer* RBHardwareBufferManager::Read<RBIndexBuffer>( RBStream& kStream )
{
    return ReadIndexBuffer(kStream);
}

/***********************************************************************************************************
 * 
 ***********************************************************************************************************/
template<>
inline RBTexture* RBHardwareBufferManager::Read<RBTexture>( RBStream& kStream )
{
    return ReadTexture(kStream);
}


#endif // __RBHARDWAREBUFFERMANAGER_H__